//
//  std::unique_ptr.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/6/29.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

/*
 智能指针是一个管理动态分配对象的类。尽管智能指针可以提供其他功能，但智能指针的定义特征是它管理动态分配的资源，并确保在适当的时间（通常在智能指针超出范围时）正确清理动态分配的对象。
 
 因此，智能指针不应该自己动态分配（否则，智能指针可能无法正确解除分配，这意味着它拥有的对象不会被释放，导致内存泄漏）。通过始终静态地分配智能指针（作为局部变量或类的组成成员），我们保证智能指针在其包含的函数或对象结束时正确地超出范围，从而确保智能指针拥有的对象被正确地释放。
 
 C ++ 11标准库附带4个智能指针类：std :: auto_ptr（你不应该使用 - 它在C ++ 17中被删除），std :: unique_ptr，std :: shared_ptr和std :: weak_ptr的。 std :: unique_ptr是迄今为止最常用的智能指针类，所以我们将首先介绍那个。在下一课中，我们将介绍std :: shared_ptr和std :: weak_ptr。
 
 std :: unique_ptr是std :: auto_ptr的C ++ 11替代品。 它应该用于管理任何不被多个对象共享的动态分配的对象。 也就是说，std :: unique_ptr应该完全拥有它管理的对象，而不是与其他类共享该所有权。 std :: unique_ptr位于<memory>标头中。

 
 std :: unique_ptr有一个重载的operator *和operator->，可以用来返回被管理的资源。 Operator *返回对托管资源的引用，并且operator->返回一个指针。
 
 请记住，std :: unique_ptr可能并不总是在管理一个对象 - 要么是因为它被创建为空（使用默认构造函数或传入nullptr作为参数），要么是因为它所管理的资源被移动到另一个std ::的unique_ptr。 因此，在我们使用这些运算符之前，我们应该检查std :: unique_ptr是否实际上有一个资源。 幸运的是，这很容易：std :: unique_ptr有一个强制转换为bool，如果std :: unique_ptr管理资源，则返回true。
 
 与std :: auto_ptr不同，std :: unique_ptr足够聪明，可以知道是使用标量删除还是数组删除，所以std :: unique_ptr可以与标量对象和数组一起使用。
 
 但是，std :: array或std :: vector（或std :: string）几乎总是比使用带固定数组，动态数组或C风格字符串的智能指针是更好的选择。
 */

#ifndef std__unique_ptr_hpp
#define std__unique_ptr_hpp

#include <stdio.h>
#include <iostream>
#include <memory>

class Resource5 {
    
public:
    Resource5(){
        std::cout << "Resource acquired\n";
    }
    ~Resource5(){
        std::cout << "Resource destroyed\n";
        
        
    }
};



/*
 std::unique_ptr<Resource5> res1(new Resource5);
 std::unique_ptr<Resource5> res2;
 
 std::cout << "res1 is " << (static_cast<bool>(res1) ? "not null\n" : "null\n");
 std::cout << "res2 is " << (static_cast<bool>(res2) ? "not null\n" : "null\n");
 
 res2 = std::move(res1);
 
 std::cout << "Ownership transferred\n";
 
 std::cout << "res1 is " << (static_cast<bool>(res1) ? "not null\n" : "null\n");
 std::cout << "res2 is " << (static_cast<bool>(res2) ? "not null\n" : "null\n");
 
 */

// std::move函数可以以非常简单的方式将左值引用转换为右值引用

//std::forward和std::move的联系和区别
//
//　　①std::move是无条件转换，不管它的参数是左值还是右值，都会被强制转换成右值。就其本身而言，它没有move任何东西。
//
//　　②std::forward是有条件转换。只有在它的参数绑定到一个右值时，它才转换它的参数到一个右值。当参数绑定到左值时，转换后仍为左值。
//
//　　③对右值引用使用std::move，对universal引用则使用std::forward
//
//　　④如果局部变量有资格进行RVO优化，不要把std::move或std::forward用在这些局部变量中

/*
 //隐式转换bool
 std::unique_ptr<Resource> res(new Resource);
 if (res) // use implicit cast to bool to ensure res contains a Resource
 std::cout << *res; // print the Resource that res is owning
 */







#endif /* std__unique_ptr_hpp */
